
import { CustomEventListener } from '../data/CustomEventListener';
import { ENTER_ROOM_COMMAND, HEART_BEAT_COMMAND } from '../proto/proto';
import { IGameHttpRequest } from './doHttp';
import { DoNetwork } from './doNetwork';
// 配置
const HEARTBEAT_INVTEVAL: number = 1000;
//10秒发送一次Ping
const PINGPONG_INVTEVAL: number = 10000;
//网络超时，弹出loading效果
const SHOW_LOADING_DELAY: number = 2000;
//网络超时，断线重连
const SHOW_RECONN_DELAY: number = 7000;
/**
 * Predefined variables
 * Name = DoNetManager
 * DateTime = Wed Oct 27 2021 15:05:10 GMT+0800 (中国标准时间)
 * Author = ff_cocoa
 * FileBasename = doNetManager.ts
 * FileBasenameNoExtension = doNetManager
 * URL = db://assets/script/donet/doNetManager.ts
 * ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/
 *
 */
 
// export class DoNetManager extends Component {
export class DoNetManager {
    private network: DoNetwork = null;

    constructor() {
        this.network = new DoNetwork(this.startReconnect.bind(this), this.reconnected.bind(this));
        // var need_listen_net_event = [
        //     "core_notify_ws_response",                //----来自通信层的websocket返回通知
        // ]
        // this.register_notify(need_listen_net_event, this.net_notify_listener.bind(this));
        CustomEventListener.on("core_notify_ws_response", this.webSockDataHandle.bind(this));
        this.netDelay = 0;                  //网络延迟
        this.pingTime = 0;                  //当前PING的时间
        this.isPing = false;                 //是否PING中
    }

    // --------------------------------------------------------------------------------------------
    // 发送http请求
    public httpRequest(request: IGameHttpRequest) {

        this.network.httpRequest(request, this.httpErrorHandle.bind(this), this.handleHttpData.bind(this));
    }

    // http连接失败处理
    private httpErrorHandle(status: number, eventName: string) {
        // http请求异常
        console.log("DoNetManager httpErrorHandle status: ", status);
        if (status == 401) {
            // // 相当于服务器回code=601的处理，重登一次
            // g_notifyer.notify_ui_event("core_notify_http_response_failed_401", {
            //     "event_name": eventName,
            //     "response_data": {}
            // })
            CustomEventListener.dispatchEvent("core_notify_http_response_failed_401", {
                "event_name": eventName,
                "response_data": {}
            });
            return;
        }
        // CustomEventListener.dispatchEvent("core_notify_http_response_failed", {
        //     "event_name": eventName,
        //     "response_data": "网络连接失败，请检查网络!"
        // });
        // console.warn("eventName:"+eventName+" 网络连接失败，请检查网络!");
    }

    // 处理http数据,需要统一处理，且其他模块无法处理的，才在此处理，其他交给各模块自行处理
    private handleHttpData(data:any, eventName: string) {
        if (data["code"] == 200) {
            console.log("http response successful");
            CustomEventListener.dispatchEvent("core_notify_http_response_successful", {
                    "event_name": eventName,
                    "response_data": data
                });
        //     // if (this._eventName == "http_gift_buy_request") {
        //     //     // 请求订单回复
        //     //     g_notifyer.notify_ui_event("core_notify_ws_unloading");
        //     //     g_notifyer.notify_ui_event("ui_notify_remove_pay_view");
        //     //     if (window.channelId === "a_hy_yyb_00" || 
        //     //         window.channelId === "a_hy_gdt_00" || 
        //     //         window.channelId === "a_hy_vivo_00" || 
        //     //         window.channelId === "a_hy_mi_00") {

        //     //         window.orderNotifyUrl = response.data.centerNotifyUrl;
        //     //         var order_data = JSON.stringify(lua_json.data);
        //     //         channel_pay(order_data);
        //     //     } else if (lua_json.data.payType == 2) {
        //     //         var conv = JSON.stringify(JSON.parse(lua_json.data.payInfo));
        //     //         wx_pay(conv);
        //     //     } else if (lua_json.data.payType == 1) {
        //     //         ali_pay(lua_json.data.payInfo);
        //     //     } else if (lua_json.data.payType == 0) {
        //     //         window.orderNotifyUrl = response.data.centerNotifyUrl;
        //     //         var order_data = JSON.stringify(lua_json.data);
        //     //         channel_pay(order_data);
        //     //     }
        //     // } else if (this._eventName === "http_do_miss_orders") {
        //     //     console.log("todo delivered_miss_orders:"+JSON.stringify(lua_json.data.extOrderIds));
        //     //     delivered_miss_orders(JSON.stringify(lua_json.data.extOrderIds));
        //     // }
        } else {
            console.log("http response error event_name:", eventName, data["msg"]);
            // 【实名认证】异常文字转换
            if (eventName == "idcard_check") {
                var idcard_check_error_msg = {
                    2001: "身份证号格式校验失败",
                    2002: "实名条目已达上限",
                    2003: "无该编码提交的实名认证记录",
                    2004: "编码已经被占用",
                }
                data["errorMsg"] = idcard_check_error_msg[data["code"]] || data["errorMsg"];
            }
            // 【实名认证】异常文字转换

            let temp = {
                "event_name": eventName,
                "response_data": data["errorMsg"] || "请求错误!",
                "response_code": data["code"]
            }
            CustomEventListener.dispatchEvent("core_notify_http_response_failed", temp);
        }

    }

    // --------------------------------------------------------------------------------------------
    //网络延迟
    private netDelay: number = 0;
    //当前PING的时间
    private pingTime: number = 0;
    //是否PING中
    private isPing: boolean = false;

    private isScheduleOpen: boolean = false;

    private pingpongTimeoutHandle: number;
    private heartbeatTimeoutHandle: number;

    private wsConnSuccFunc: Function;
    private wsConnFailFunc: Function;


    private WebSockConneted() {
        // 启动心跳与延迟检测
        this.startHeartbeat();
        // 立刻发一次心跳
        this.pingpong();
        // 通知websocket连接成功，对应模块进行下一步处理
        // CustomEventListener.dispatchEvent("net_notify_ws_connected");
        this.wsConnSuccFunc();
    }

    private WebSockFailConnect() {
        // console.warn("连接游戏服务器失败!\n请确保网络正常后再尝试");
        // let temp = {
        //     // "type": msgbox_type.know,
        //     "text": "连接游戏服务器失败!\n请确保网络正常后再尝试",
        //     // "fairy": fairy_type.cry,
        // }
        // CustomEventListener.dispatchEvent("ui_notify_open_msg_box", temp);
        this.wsConnFailFunc();
    }

    // 连接websocket
    public connectWebSock(url: string, succHandle: Function, failHandle: Function) {
        this.wsConnSuccFunc = succHandle;
        this.wsConnFailFunc = failHandle;
        this.network.ws_connect(url, this.WebSockConneted.bind(this), this.WebSockFailConnect.bind(this));
    }

    private pingpong() {
        // 发送心跳
        var data = {};
        // data["cmd"] = HEART_BEAT_COMMAND.MSG_HEART_PING_PONG;
        this.network.wsRequestPb(data);

        var date = new Date();
        this.pingTime = Number(date.getTime());
        this.netDelay = 0;
        this.isPing = true;
    }

    private heartbeat() {
        //处理网络延迟，超时
        if (this.isPing == false) return;

        var date = new Date();
        var cur_time_stamp = Number(date.getTime());
        this.netDelay = cur_time_stamp - this.pingTime;

        // 不同延迟不同处理
        if (this.netDelay > SHOW_RECONN_DELAY) {
            console.log("DoNetManager heartbeat netDelay > SHOW_RECONN_DELAY");
        }
        else if (this.netDelay > SHOW_LOADING_DELAY) {
            CustomEventListener.dispatchEvent("core_notify_ws_loading");
            console.log("DoNetManager heartbeat netDelay > SHOW_LOADING_DELAY ");
        }
    }

    
    private startHeartbeat() {
        let self = this;
        if (self.isScheduleOpen == false) {
            console.log("DoNetManager startHeartbeat @@@@ 开启心跳计时器");
            self.pingpongTimeoutHandle = setTimeout(()=>{self.pingpong}, PINGPONG_INVTEVAL);
            self.heartbeatTimeoutHandle = setTimeout(()=>{self.heartbeat}, HEARTBEAT_INVTEVAL);
            // this.schedule(this.pingpong, PINGPONG_INVTEVAL);
            // this.schedule(this.heartbeat, HEARTBEAT_INVTEVAL);
            self.isScheduleOpen = true;
        }
    }

    private stopHeartbeat() {
        let self = this;
        self.isPing = false;

        if (self.isScheduleOpen == true) {
            console.log("DoNetManager stopHeartbeat 关闭心跳计时器");
            clearTimeout(self.pingpongTimeoutHandle);
            clearTimeout(self.heartbeatTimeoutHandle);
            // this.unschedule(this.heartbeat);
            // this.unschedule(this.pingpong);
            self.isScheduleOpen = false;
        }
    }
    public startReconnect() {
        this.stopHeartbeat();
    }

    public reconnected() {
        // 启动心跳与延迟检测
        this.startHeartbeat();
        // 通知websocket连接成功，对应模块进行下一步处理
        CustomEventListener.dispatchEvent("core_notify_ws_reconnect_success");
    }

    // 客户端主动断开ws的接口
    public closeWebSock() {
        console.log("DoNetManager closeWebSock 客户端主动断开ws");
        this.stopHeartbeat();
        this.network.closeWebSock();
    }

    private webSockDataHandle(event: any) {
        let self = this;
        let eventName = event["event_name"];
        let response_data = event["response_data"];
        let response_code = event["response_code"];

        if (HEART_BEAT_COMMAND.MSG_HEART_BEAT_PUSH == eventName) {
            //--心跳
            // cc.log("MSG_HEART_BEAT_PUSH:"+JSON.stringify(response_data));
            var response_obj = response_data.userListResponse;
        } else if (HEART_BEAT_COMMAND.MSG_HEART_PING_PONG == eventName) {
            //ping pong心跳
            console.log("MSG_HEART_PING_PONG:");
            var date = new Date();
            self.netDelay = Number(date.getTime()) - self.pingTime;
            self.isPing = false;
        } else if (ENTER_ROOM_COMMAND.MSG_RECONNECT_ENTER_ACK == eventName) {
            //断线重连回复
            var response_obj
            console.log("data:" + JSON.stringify(response_data));
            response_obj = response_data.joinTableResponse;
            // set_room_info_on_reconnect(response_obj);
            //--重连到场景
            CustomEventListener.dispatchEvent("ui_notify_reconnect_scene", {
                "event_name": "ui_notify_reconnect_scene",
                "response_data": {"response": response_obj}
            });    
        } else if (ENTER_ROOM_COMMAND.MSG_RECONNECT_ENTER_FAILED == eventName) {
            // --断线重连失败,可能牌桌不存在了
            console.log("MSG_RECONNECT_ENTER_FAILED:");
        }
    }

    public webSockRequestPB(data: IRequestProto) {
        this.network.wsRequestPb(data)
    }

    public cancelWebSockConfirm() {
        this.network.cancelWebSockConfirm();
    }
}

